package com.qidian.buy.config;

import com.qidian.buy.service.ItemSearchService;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
*@author 戴着假发的程序员
*@company 起点编程
*@date 2023/9/15 11:40
*/
@Component // 将我们的监听者交给spring
public class ItemIdReceive implements ChannelAwareMessageListener {
    @Autowired
    private ItemSearchService searchService;

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        // 获取消息的唯一性ID
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        Long itemId = null;
        try {
            String msg = new String(message.getBody(),"UTF-8");
            // 获取商品的id
            itemId = new Long(msg);
            // 只要拿到消息就立刻确认, 防止消息被其他的节点重复消息
            // 手动确认
            channel.basicAck(deliveryTag,true);
            // 将商品加入索引库
            // 通过商品的id将商品加入索引库
            searchService.insert(itemId); // 如果这里是重操作，建议全部应答完成
        } catch (IOException e) {
            // 重试
            // 如果这里的并发量较大，建议将失败的信息保存到redis中，等到系统资源充裕之后再重新处理失败的信息。
            // 我们直接重试10次
            int count = 0;
            while (count < 10){
                TimeUnit.SECONDS.sleep(5);
                try {
                    searchService.insert(itemId);
                } catch (Exception ex) {
                    // 纪录异常
                }
                count ++;
            }
            if(count >= 10) {
                // 将这个信息也要保存起来  保存到redis
                throw new RuntimeException(e);
            }
        }
    }
}
